package com.skivingcloud.report.service.impl;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.mybatisflex.spring.service.impl.ServiceImpl;
import com.skivingcloud.common.exceptions.BusinessException;
import com.skivingcloud.common.utils.JacksonUtil;
import com.skivingcloud.report.constants.JdbcConstants;
import com.skivingcloud.report.constants.ReportConstant;
import com.skivingcloud.report.dto.*;
import com.skivingcloud.report.entity.ReportDataSetTransform;
import com.skivingcloud.report.entity.ReportDataSource;
import com.skivingcloud.report.mapper.ReportDataSetTransformMapper;
import com.skivingcloud.report.service.ReportDataSetParamService;
import com.skivingcloud.report.service.ReportDataSetTransformService;
import com.skivingcloud.report.service.ReportDataSourceService;
import com.skivingcloud.report.service.TransformStrategy;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Service;
import com.mybatisflex.core.paginate.Page;
import com.mybatisflex.core.query.QueryWrapper;
import com.skivingcloud.common.utils.PageParameter;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 数据集数据转换 服务层实现。
 *
 * @author skivingcloud
 * @since 2024-09-12
 */
@Service
public class ReportDataSetTransformServiceImpl extends ServiceImpl<ReportDataSetTransformMapper, ReportDataSetTransform> implements ReportDataSetTransformService, InitializingBean, ApplicationContextAware {
    private final Map<String, TransformStrategy> queryServiceImplMap = new HashMap<>();
    private ApplicationContext applicationContext;
    private ReportDataSourceService reportDataSourceService;
    private ReportDataSetParamService reportdataSetParamService;

    public ReportDataSetTransformServiceImpl(ReportDataSourceService reportDataSourceService, ReportDataSetParamService reportdataSetParamService) {
        this.reportDataSourceService = reportDataSourceService;
        this.reportdataSetParamService = reportdataSetParamService;
    }

    public TransformStrategy getTarget(String type) {
        return queryServiceImplMap.get(type);
    }
    @Override
    public void afterPropertiesSet() {
        Map<String, TransformStrategy> beanMap = applicationContext.getBeansOfType(TransformStrategy.class);
        //遍历该接口的所有实现，将其放入map中
        queryServiceImplMap.putAll(beanMap.values().stream()
                .collect(Collectors.toMap(TransformStrategy::type, Function.identity())));
    }
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }

    /**
     * 分页查询数据集数据转换
     *
     * @param parameter 查询参数
     * @return 分页查询结果
     */
    @Override
    public Page<ReportDataSetTransform> queryByPage(PageParameter<ReportDataSetTransform> parameter){
        Page<ReportDataSetTransform> page = new Page<>(parameter.getPage(), parameter.getPageSize());
        QueryWrapper queryWrapper = QueryWrapper.create();
        if (parameter.getParam() != null) {
            //查询条件
            if (StringUtils.isNoneBlank(parameter.getParam().getId())) {
                queryWrapper.and(ReportDataSetTransform::getId).like(parameter.getParam().getId());
            }
            if (StringUtils.isNoneBlank(parameter.getParam().getSetCode())) {
                queryWrapper.and(ReportDataSetTransform::getSetCode).like(parameter.getParam().getSetCode());
            }
            if (StringUtils.isNoneBlank(parameter.getParam().getTransformType())) {
                queryWrapper.and(ReportDataSetTransform::getTransformType).like(parameter.getParam().getTransformType());
            }
            if (StringUtils.isNoneBlank(parameter.getParam().getTransformScript())) {
                queryWrapper.and(ReportDataSetTransform::getTransformScript).like(parameter.getParam().getTransformScript());
            }
            if (StringUtils.isNoneBlank(parameter.getParam().getEnableFlag())) {
                queryWrapper.and(ReportDataSetTransform::getEnableFlag).like(parameter.getParam().getEnableFlag());
            }
            if (StringUtils.isNoneBlank(parameter.getParam().getDeleteFlag())) {
                queryWrapper.and(ReportDataSetTransform::getDeleteFlag).like(parameter.getParam().getDeleteFlag());
            }
            if (StringUtils.isNoneBlank(parameter.getParam().getCreateBy())) {
                queryWrapper.and(ReportDataSetTransform::getCreateBy).like(parameter.getParam().getCreateBy());
            }
            if (StringUtils.isNoneBlank(parameter.getParam().getUpdateBy())) {
                queryWrapper.and(ReportDataSetTransform::getUpdateBy).like(parameter.getParam().getUpdateBy());
            }
        }
        return this.page(page, queryWrapper);
    }

    /**
     * 测试 数据转换是否正确
     *
     * @param param 参数
     * @return 测试数据
     */
    @Override
    public OriginalDataDto testTransform(DataSetDto param) throws JsonProcessingException {
        OriginalDataDto originalDataDto = new OriginalDataDto();
        String sourceCode = param.getSourceCode();
        //1.获取数据源
        ReportDataSource dataSource;
        String dynSentence = param.getDynSentence();
        if (param.getSetType().equals(ReportConstant.SetTypeEnum.HTTP.getCodeValue())) {
            //http不需要数据源，兼容已有的逻辑，将http所需要的数据塞进DataSource
            dataSource = new ReportDataSource();
            Map<String, Object> sourceConf = new HashMap<>();
            sourceConf.put("apiUrl", param.getApiUrl());
            sourceConf.put("method", param.getMethod());
            sourceConf.put("header", param.getHeader());
            sourceConf.put("body", param.getBody());
            dataSource.setSourceConfig(JacksonUtil.mapToJsonString(sourceConf));
            dataSource.setSourceType(JdbcConstants.HTTP);
            if (StringUtils.isNotBlank(param.getBody())) {
                dynSentence = param.getBody();
            } else {
                dynSentence = "{}";
            }
        } else {
            dataSource = reportDataSourceService.getById(sourceCode);
        }

        //3.参数替换
        //3.1参数校验
        boolean verification = reportdataSetParamService.verification(param.getDataSetParamDtoList(), null);
        if (!verification) {
            throw new BusinessException("规则参数校验不通过");
        }

        dynSentence = reportdataSetParamService.transform(param.getDataSetParamDtoList(), dynSentence);
        //4.获取数据
        DataSourceDto dataSourceDto = new DataSourceDto();
        BeanUtils.copyProperties(dataSource, dataSourceDto);
        dataSourceDto.setDynSentence(dynSentence);
        dataSourceDto.setContextData(setContextData(param.getDataSetParamDtoList()));

        //获取total,判断DataSetParamDtoList中是否传入分页参数
        Map<String, Object> collect = param.getDataSetParamDtoList().stream().collect(Collectors.toMap(DataSetParamDto::getParamName, DataSetParamDto::getSampleItem));
        if (collect.containsKey("pageNumber") && collect.containsKey("pageSize")) {
            param.setContextData(collect);
            long total = reportDataSourceService.total(dataSourceDto, param);
            originalDataDto.setTotal(total);
        }

        List<Map<String, Object>> data = reportDataSourceService.execute(dataSourceDto);
        //5.数据转换
        List<Map<String, Object>> transform = transform(param.getDataSetTransformDtoList(), data);
        originalDataDto.setData(transform);
        return originalDataDto;
    }

    private List<Map<String, Object>> transform(List<DataSetTransformDto> dataSetTransformDtoList, List<Map<String, Object>> data) throws JsonProcessingException {
        if (dataSetTransformDtoList == null || dataSetTransformDtoList.isEmpty()) {
            return data;
        }

        for (DataSetTransformDto dataSetTransformDto : dataSetTransformDtoList) {
            data = getTarget(dataSetTransformDto.getTransformType()).transform(dataSetTransformDto, data);
        }
        return data;
    }

    /**
     * dataSetParamDtoList转map
     * @param dataSetParamDtoList 参数
     * @return 转换后数据
     */
    public Map<String, Object> setContextData(List<DataSetParamDto> dataSetParamDtoList) {
        Map<String, Object> map = new HashMap<>();
        if (null != dataSetParamDtoList && !dataSetParamDtoList.isEmpty()) {
            dataSetParamDtoList.forEach(dataSetParamDto -> map.put(dataSetParamDto.getParamName(), dataSetParamDto.getSampleItem()));
        }
        return map;
    }
}
